package moxl.relaxng.schema;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import moxl.dom.MoxlElement;

public class SimplifiedRelaxNgGrammar
{
	private final PatternFactory patternFactory = new PatternFactory();

	private Map<String, Pattern> definedPatterns = new HashMap<String, Pattern>();
	private Pattern startPattern;

	public SimplifiedRelaxNgGrammar(MoxlElement grammarElement)
	{
		MoxlElement startElement = grammarElement.getFirstChildElement(RelaxNgSchemaElementType.start.getName());
		if (startElement == null)
		{
			throw new IllegalArgumentException("Grammar element does not contain a start element");
		}
		MoxlElement startElementPatternElement = startElement.getChildElement(0);
		if (startElementPatternElement == null)
		{
			throw new IllegalArgumentException("Grammar start element does not contain a pattern");
		}
		startPattern = patternFactory.createPattern(startElementPatternElement);
		List<MoxlElement> defineElements = grammarElement.getChildElements(RelaxNgSchemaElementType.define.getName());
		for (MoxlElement defineElement : defineElements)
		{
			Pattern definePattern = patternFactory.createPattern(defineElement.getChildElement(0));
			definedPatterns.put(defineElement.getAttributeObjByString("name").getValue(), definePattern);
		}
	}

	/**
	 * "If we can compute derivatives, then we can determine whether a pattern matches a node: a pattern matches a node if the derivative of the pattern with
	 * respect to the node is nullable."
	 */
	public boolean matches(MoxlElement documentEl)
	{
		ChildDerivativeComputer childDerivativeComputer = new ChildDerivativeComputer();
		Pattern derivative = childDerivativeComputer.childDeriv(null, startPattern, documentEl);
		return derivative.nullable();
	}

}
